package com.badminton.web.service.impl;

import cn.hutool.core.date.DateUtil;
import com.badminton.web.enums.TagEnum;
import com.badminton.web.enums.UserTypeEnum;
import com.badminton.web.exception.BusinessException;
import com.badminton.web.mapper.TagWeightMapper;
import com.badminton.web.mapper.UserEvaluateMapper;
import com.badminton.web.mapper.UserMapper;
import com.badminton.web.model.TagWeightDO;
import com.badminton.web.model.UserDO;
import com.badminton.web.model.UserEvaluateDO;
import com.badminton.web.model.request.*;
import com.badminton.web.model.response.QueryUserEvaluateInfoResponseVO;
import com.badminton.web.model.response.QueryUserInfoResponseVO;
import com.badminton.web.model.response.UserEvaluateVO;
import com.badminton.web.service.IBadmintonService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.time.LocalTime;
import java.util.stream.Collectors;

/**
 * @Author: peng.chen
 * @CreateTime: 2025-02-11
 * @Description:
 * @Version: 1.0.0
 */
@Service
@Slf4j
public class BadmintonServiceImpl implements IBadmintonService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserEvaluateMapper userEvaluateMapper;
    @Autowired
    private TagWeightMapper tagWeightMapper;

    @Override
    public Long register(RegisterRequestVO registerRequestVO) {
        UserDO userDO = userMapper.queryUserInfo(null, registerRequestVO.getName(), registerRequestVO.getPhone(), UserTypeEnum.USER.getCode());
        if (Objects.nonNull(userDO)) {
            throw new BusinessException("用户名或手机号已注册！");
        } else {
            UserDO newUserDO = new UserDO();
            newUserDO.setName(registerRequestVO.getName());
            newUserDO.setPassword(registerRequestVO.getPassword());
            newUserDO.setPhone(registerRequestVO.getPhone());
            newUserDO.setEmail(registerRequestVO.getEmail());
            newUserDO.setType(UserTypeEnum.USER.getCode());
            Integer row = userMapper.insertUserInfo(newUserDO);
            UserDO resultUser = userMapper.queryUserInfo(null, registerRequestVO.getName(), registerRequestVO.getPhone(), UserTypeEnum.USER.getCode());
            if (Objects.nonNull(row) && row > 0) {
                return resultUser.getId();
            } else {
                throw new BusinessException("注册失败！");
            }
        }
    }

    @Override
    public Long login(LoginRequestVO loginRequestVO) {
        UserDO userDO = userMapper.queryUserInfo(null, loginRequestVO.getName(), loginRequestVO.getPhone(), null);
        if (Objects.isNull(userDO)) {
            throw new BusinessException("用户名或手机号不存在！请先注册！");
        } else {
            if (!userDO.getPassword().equals(loginRequestVO.getPassword())) {
                throw new BusinessException("密码错误！请重新输入!");
            }
        }
        return userDO.getId();
    }

    @Override
    public QueryUserInfoResponseVO queryUserInfo(QueryUserInfoRequestVO queryUserInfoRequestVO) {
        QueryUserInfoResponseVO queryUserInfoResponseVO = new QueryUserInfoResponseVO();
        List<UserDO> userDOS = new ArrayList<>();
        Integer count = 0;
        if (Objects.nonNull(queryUserInfoRequestVO.getId())) {
            UserDO user = userMapper.queryUserInfo(queryUserInfoRequestVO.getId(), null, null, null);
            if (Objects.nonNull(user)) {
                userDOS.add(user);
                count = 1;
            }
        } else {
            queryUserInfoRequestVO.setOffset(queryUserInfoRequestVO.getPageNum() * queryUserInfoRequestVO.getPageSize());
            userDOS = userMapper.queryUserInfoByPage(queryUserInfoRequestVO);
            count = userMapper.countUserInfo(queryUserInfoRequestVO);
        }
        queryUserInfoResponseVO.setUsers(userDOS);
        queryUserInfoResponseVO.setTotalNum(count);
        queryUserInfoResponseVO.setTotalPage(count % queryUserInfoRequestVO.getPageSize() == 0 ? count / queryUserInfoRequestVO.getPageSize() : count / queryUserInfoRequestVO.getPageSize() + 1);
        return queryUserInfoResponseVO;
    }

    @Override
    public Boolean updateUserInfo(UpdateUserInfoRequestVO updateUserInfoRequestVO) {
        if (Objects.isNull(updateUserInfoRequestVO.getId())) {
            throw new BusinessException("用户ID不能为空！");
        }
        UserDO userDO = userMapper.queryUserInfo(updateUserInfoRequestVO.getId(), null, null, UserTypeEnum.USER.getCode());
        if (Objects.isNull(userDO)) {
            throw new BusinessException("用户不存在！");
        }
        userDO.setEmail(updateUserInfoRequestVO.getEmail());
        userDO.setName(updateUserInfoRequestVO.getName());
        userDO.setPhone(updateUserInfoRequestVO.getPhone());
        userDO.setProficiency(updateUserInfoRequestVO.getProficiency());
        userDO.setSex(updateUserInfoRequestVO.getSex());
        userDO.setAge(updateUserInfoRequestVO.getAge());
        userDO.setFreeStartTime(updateUserInfoRequestVO.getFreeStartTime());
        userDO.setFreeEndTime(updateUserInfoRequestVO.getFreeEndTime());
        return userMapper.updateUserInfo(userDO) > 0;
    }

    @Override
    public QueryUserEvaluateInfoResponseVO queryUserEvaluateInfo(QueryUserEvaluateInfoRequestVO queryUserEvaluateInfoRequestVO) {
        List<UserEvaluateDO> userEvaluateDOS = userEvaluateMapper.queryUserEvaluateInfoByPage(queryUserEvaluateInfoRequestVO.getId(),
                queryUserEvaluateInfoRequestVO.getEvaluateUserId(), queryUserEvaluateInfoRequestVO.getPageNum() * queryUserEvaluateInfoRequestVO.getPageSize(), queryUserEvaluateInfoRequestVO.getPageSize());
        Integer totalNum = userEvaluateMapper.countUserEvaluateInfo(queryUserEvaluateInfoRequestVO.getId(), queryUserEvaluateInfoRequestVO.getEvaluateUserId());

        List<UserEvaluateVO> userEvaluates = new ArrayList<>();
        for (UserEvaluateDO userEvaluateDO : userEvaluateDOS) {
            UserEvaluateVO userEvaluateVO = new UserEvaluateVO();
            userEvaluateVO.setUser(userMapper.queryUserInfo(userEvaluateDO.getUserId(), null, null, UserTypeEnum.USER.getCode()));
            userEvaluateVO.setEvaluateUser(userMapper.queryUserInfo(userEvaluateDO.getEvaluateUserId(), null, null, UserTypeEnum.USER.getCode()));
            userEvaluateVO.setScore(userEvaluateDO.getScore());
            userEvaluateVO.setEvaluateTime(userEvaluateDO.getEvaluateTime());
            userEvaluates.add(userEvaluateVO);
        }
        QueryUserEvaluateInfoResponseVO queryUserEvaluateInfoResponseVO = new QueryUserEvaluateInfoResponseVO();
        queryUserEvaluateInfoResponseVO.setUserEvaluates(userEvaluates);
        queryUserEvaluateInfoResponseVO.setTotalNum(totalNum);
        queryUserEvaluateInfoResponseVO.setTotalPage(totalNum % queryUserEvaluateInfoRequestVO.getPageSize() == 0 ? totalNum / queryUserEvaluateInfoRequestVO.getPageSize() : totalNum / queryUserEvaluateInfoRequestVO.getPageSize() + 1);
        return queryUserEvaluateInfoResponseVO;
    }

    @Override
    public Long match(Long id) {
        // 加权欧几里得距离算法
        UserDO userDO = userMapper.queryUserInfo(id, null, null, UserTypeEnum.USER.getCode());
        if (Objects.isNull(userDO)) {
            throw new BusinessException("用户不存在！");
        }
        List<UserDO> userDOList = userMapper.queryAllUserInfo().stream().filter(r -> !Objects.equals(r.getId(), id)).collect(Collectors.toList());
        // 得出每个用户的和当前用户的 加权欧几里得距离
        Map<Long, Double> distanceMap = new HashMap<>();
        userDOList.forEach(user -> {
            double diff = calculateDifference(userDO, user);
            distanceMap.put(user.getId(), diff);
        });
        // 获取distanceMap中value最大值的key
        for (Map.Entry<Long, Double> entry : distanceMap.entrySet()) {
            if (Objects.equals(entry.getValue(), Collections.min(distanceMap.values()))) {
                return entry.getKey();
            }
        }
        throw new BusinessException("无匹配用户！");
    }

    /**
     * 计算两个用户的匹配度（加权欧几里得距离）
     */
    private double calculateDifference(UserDO u1, UserDO u2) {
        Map<String, Integer> tagWeightMap = new HashMap<>();
        for (TagWeightDO tagWeightDO : tagWeightMapper.queryTagWeightInfo()) {
            tagWeightMap.put(tagWeightDO.getTagCode(), tagWeightDO.getWeight());
        }
        Integer proficiencyWeight = tagWeightMap.get(TagEnum.PROFICIENCY.getCode());
        Integer ageWeight = tagWeightMap.get(TagEnum.AGE.getCode());
        Integer sexWeight = tagWeightMap.get(TagEnum.SEX.getCode());
        Integer timeWeight = tagWeightMap.get(TagEnum.FREE_TIME.getCode());

        // 计算差异度
        double proficiencyDiff = Math.pow(u1.getProficiency() - u2.getProficiency(), 2);
        double ageDiff = Math.pow(u1.getAge() - u2.getAge(), 2);
        double sexDiff = Math.pow(u1.getSex() - u2.getSex(), 2);

        // 解析字符串为 LocalTime
        LocalTime s1 = LocalTime.parse(u1.getFreeStartTime(), DateTimeFormatter.ofPattern("HH:mm"));
        LocalTime e1 = LocalTime.parse(u1.getFreeEndTime(), DateTimeFormatter.ofPattern("HH:mm"));
        LocalTime s2 = LocalTime.parse(u2.getFreeStartTime(), DateTimeFormatter.ofPattern("HH:mm"));
        LocalTime e2 = LocalTime.parse(u2.getFreeEndTime(), DateTimeFormatter.ofPattern("HH:mm"));

        // 计算交集的开始时间和结束时间
        Long timeDiff = 0L;
        LocalTime intersectionStart = s1.isAfter(s2) ? s1 : s2;
        LocalTime intersectionEnd = e1.isBefore(e2) ? e1 : e2;
        if (intersectionStart.isBefore(intersectionEnd)) {
            timeDiff =  Duration.between(intersectionStart, intersectionEnd).toMinutes();// 返回交集时长（分钟）
        }

        // 加权欧几里得距离
        return Math.sqrt(proficiencyWeight * proficiencyDiff + ageWeight * ageDiff + sexWeight * sexDiff + timeWeight * timeDiff);
    }

    @Override
    public Boolean evaluate(EvaluateRequestVO evaluateRequestVO) {
        if (Objects.isNull(evaluateRequestVO.getId())) {
            throw new BusinessException("用户ID不能为空！");
        }
        if (Objects.isNull(evaluateRequestVO.getEvaluateUserId())) {
            throw new BusinessException("被评价用户ID不能为空！");
        }
        if (Objects.isNull(evaluateRequestVO.getScore())) {
            throw new BusinessException("评价分数不能为空！");
        }
        UserEvaluateDO userEvaluateDO = new UserEvaluateDO();
        userEvaluateDO.setUserId(evaluateRequestVO.getId());
        userEvaluateDO.setEvaluateUserId(evaluateRequestVO.getEvaluateUserId());
        userEvaluateDO.setScore(evaluateRequestVO.getScore());
        userEvaluateDO.setEvaluateTime(new Date());
        return userEvaluateMapper.insertUserEvaluateInfo(userEvaluateDO) > 0;
    }

    @Override
    public List<TagWeightDO> queryTagWeightInfo() {
        return tagWeightMapper.queryTagWeightInfo();
    }

    @Override
    public Boolean updateTagWeightInfo(UpdateTagWeightInfoRequestVO updateTagWeightInfoRequestVO) {
        return tagWeightMapper.updateTagWeightInfo(updateTagWeightInfoRequestVO.getTagCode(), updateTagWeightInfoRequestVO.getWeight()) > 0;
    }
}
